package com.central.scheduler.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.central.common.enums.TaskType;
import com.central.common.model.PageResult;
import com.central.common.model.Result;
import com.central.common.model.SysUser;
import com.central.common.model.TaskDefinition;
import com.central.common.service.impl.SuperServiceImpl;
import com.central.common.utils.UserRoleUtil;
import com.central.scheduler.api.entity.treeview.Instance;
import com.central.scheduler.api.entity.treeview.TreeViewEntity;
import com.central.scheduler.api.enums.Status;
import com.central.scheduler.api.service.IProcessDefinitionService;
import com.central.scheduler.api.service.IScheduleService;
import com.central.scheduler.api.utils.DsfCycle;
import com.central.scheduler.common.Constants;
import com.central.scheduler.common.entity.DependentItem;
import com.central.scheduler.common.entity.DependentTaskModel;
import com.central.scheduler.common.entity.TaskNode;
import com.central.scheduler.common.entity.TaskNodeRelation;
import com.central.scheduler.common.enums.ReleaseState;
import com.central.scheduler.common.graph.DAG;
import com.central.scheduler.common.task.dependent.DependentParameters;
import com.central.scheduler.common.task.subprocess.SubProcessParameters;
import com.central.scheduler.common.thread.Stopper;
import com.central.scheduler.common.utils.DateUtils;
import com.central.scheduler.common.utils.JSONUtils;
import com.central.scheduler.common.utils.SnowFlakeUtils;
import com.central.scheduler.dao.entity.TaskNodeParam;
import com.central.scheduler.dao.mapper.*;
import com.central.scheduler.dao.model.*;
import com.central.scheduler.service.exception.ServiceException;
import com.central.scheduler.service.process.ProcessService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author Tindy
 * @date 2022/1/6
 * @describe
 */
@Slf4j
@Service
public class ProcessDefinitionServiceImpl extends SuperServiceImpl<ProcessDefinitionMapper, ProcessDefinition> implements IProcessDefinitionService {
    @Autowired
    private ProcessDefinitionOwnersMapper processDefinitionOwnersMapper;
    @Autowired
    private ProcessDefinitionLogMapper processDefinitionLogMapper;
    @Autowired
    private ProcessService processService;
    @Autowired
    private ProcessTaskRelationMapper processTaskRelationMapper;
    @Autowired
    private ProcessTaskRelationLogMapper processTaskRelationLogMapper;
    @Autowired
    private ProcessInstanceMapper processInstanceMapper;
    @Autowired
    private TaskInstanceMapper taskInstanceMapper;
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private IScheduleService scheduleService;
    @Autowired
    private ScheduleSubProcessMapper scheduleSubProcessMapper;
    @Autowired
    private ProcessLineageMapper processLineageMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result saveOrUpdateProcess(SysUser user, ProcessDefinition processDefinition, Boolean isFromProcessDefine) throws SnowFlakeUtils.SnowFlakeException {
        ProcessDefinition processDefinition2 = getById(processDefinition.getId());
        if (processDefinition2 != null) {
            //检查用户是否由权限
            if (!checkOperationPermission(user, processDefinition2)) return Result.failed("操作失败，用户权限不足");
            //检查工作流是否为上线状态
            if (processDefinition2.getReleaseState() == ReleaseState.ONLINE) return Result.failed("上线状态，不可操作");
            //检查作业名唯一性
            if (!checkTaskNameUnique(processDefinition)) return Result.failed("操作失败，作业名不唯一");
            //检查流程闭环错误
            List<String> loops = getProcessClosedLoop(processDefinition);
            if (loops.size() > 0) return Result.failed("操作失败，流程中存在闭环作业:" + loops);
            processDefinition.setProId(processDefinition2.getProId());
            processDefinition.setProName(processDefinition2.getProName());
            processDefinition.setCode(processDefinition2.getCode());
            processService.saveProcessDefine(processDefinition, isFromProcessDefine);
            processService.saveTaskRelation(user.getCurrentProjectId(), processDefinition.getCode(), processDefinition.getVersion(), processDefinition.getTaskRelationList());
            //当作业流存在dependent作业时，保存更新作业流血缘关系
            //删除旧血缘关系
            processLineageMapper.delete(new QueryWrapper<ProcessLineage>().eq("dest_process_code",processDefinition.getCode()));
            List<TaskNodeParam> taskNodeParams = processDefinition.getTaskNodeParams();
            List<ProcessLineage> processLineages=new ArrayList<>();
            for (TaskNodeParam taskNodeParam : taskNodeParams) {
                if(taskNodeParam.getTaskType()== TaskType.DEPENDENT){
                    DependentParameters dependentParameters = taskNodeParam.getDependentParameters();
                    List<DependentTaskModel> dependTaskList = dependentParameters.getDependTaskList();
                    for (DependentTaskModel dependentTaskModel : dependTaskList) {
                        for (DependentItem dependentItem : dependentTaskModel.getDependItemList()) {
                            processLineages.add(new ProcessLineage(dependentItem.getDefinitionCode(),processDefinition.getCode()));
                        }
                    }
                }
            }
            if(!processLineages.isEmpty()){
                processLineageMapper.batchInsert(processLineages);
            }
            return Result.succeed("操作成功");
        } else {
            //检查作业名唯一性
            if (!checkTaskNameUnique(processDefinition)) return Result.failed("操作失败，作业名不唯一");
            //检查流程闭环错误
            List<String> loops = getProcessClosedLoop(processDefinition);
            if (loops.size() > 0) return Result.failed("操作失败，流程中存在闭环作业:" + loops);
            processDefinition.setProId(user.getCurrentProjectId());
            processDefinition.setProName(user.getProName());
            long code = SnowFlakeUtils.getInstance().nextId();
            processDefinition.setCode(code);
            processDefinition.setReleaseState(ReleaseState.OFFLINE);
            processDefinition.setScheduleReleaseState(ReleaseState.OFFLINE);
            processService.saveProcessDefine(processDefinition, true);
            processService.saveTaskRelation(user.getCurrentProjectId(), processDefinition.getCode(), processDefinition.getVersion(), processDefinition.getTaskRelationList());
            ProcessDefinitionOwners owners = new ProcessDefinitionOwners();
            owners.setProcessDefinitionId(processDefinition.getId());
            owners.setOwners(Arrays.asList(user.getUsername()));
            processDefinitionOwnersMapper.insert(owners);
            //当作业流存在dependent作业时，保存更新作业流血缘关系
            //删除旧血缘关系
            List<TaskNodeParam> taskNodeParams = processDefinition.getTaskNodeParams();
            List<ProcessLineage> processLineages=new ArrayList<>();
            for (TaskNodeParam taskNodeParam : taskNodeParams) {
                if(taskNodeParam.getTaskType()== TaskType.DEPENDENT){
                    DependentParameters dependentParameters = taskNodeParam.getDependentParameters();
                    List<DependentTaskModel> dependTaskList = dependentParameters.getDependTaskList();
                    for (DependentTaskModel dependentTaskModel : dependTaskList) {
                        for (DependentItem dependentItem : dependentTaskModel.getDependItemList()) {
                            processLineages.add(new ProcessLineage(dependentItem.getDefinitionCode(),processDefinition.getCode()));
                        }
                    }
                }
            }
            if(!processLineages.isEmpty()){
                processLineageMapper.batchInsert(processLineages);
            }
            return Result.succeed("操作成功");
        }
    }

    /**
     * 获取闭环流程
     *
     * @param processDefinition
     * @return
     */
    private List<String> getProcessClosedLoop(ProcessDefinition processDefinition) {
        List<ProcessTaskRelationLog> taskRelationList = processDefinition.getTaskRelationList();
        DsfCycle dsfCycle = new DsfCycle();
        for (ProcessTaskRelationLog r : taskRelationList) {
            dsfCycle.addLine(r.getPreTaskName(), r.getPostTaskName());
        }
        return dsfCycle.find();
    }

    /**
     * 检查作业流作业名的唯一性
     *
     * @param processDefinition
     */
    private Boolean checkTaskNameUnique(ProcessDefinition processDefinition) {
        List<TaskNodeParam> taskNodeParams = processDefinition.getTaskNodeParams();
        long count = taskNodeParams.stream().map(x -> x.getName()).distinct().count();
        return taskNodeParams.size() == count;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result setOwners(SysUser user, List<String> owners, Long processId) {
        ProcessDefinition processDefinition = getById(processId);
        if (processDefinition != null) {
            //检查用户是否由权限
            if (!checkOperationPermission(user, processDefinition)) return Result.failed("操作失败，用户权限不足");
            ProcessDefinitionOwners owners2 = processDefinitionOwnersMapper.selectOne(new QueryWrapper<ProcessDefinitionOwners>().eq("process_definition_id", processId));
            owners2.setOwners(owners);
            processDefinitionOwnersMapper.updateById(owners2);
            return Result.succeed("操作成功");
        } else return Result.failed("作业流不存在");
    }

    @Override
    public PageResult<ProcessDefinition> findProcesses(Map<String, Object> params) {
        Page<ProcessDefinition> page = new Page<>(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"));
        List<ProcessDefinition> list = baseMapper.findProcesses(page, params);
        long total = page.getTotal();
        return PageResult.<ProcessDefinition>builder().data(list).code(0).count(total).build();
    }

    @Override
    public List<Map<String, Object>> findProcessLogs(Long proId, Long code) {
        return processDefinitionLogMapper.selectMaps(new QueryWrapper<ProcessDefinitionLog>().eq("pro_id", proId).eq("code", code).select("id", "name", "version", "create_time").orderByDesc("version"));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result switchVersion(SysUser user, Long logId) {
        ProcessDefinitionLog processDefinitionLog = processDefinitionLogMapper.selectById(logId);
        ProcessDefinition processDefinition = baseMapper.queryByCode(processDefinitionLog.getCode(), user.getCurrentProjectId());
        if (processDefinition != null) {
            //检查用户是否由权限
            if (!checkOperationPermission(user, processDefinition)) return Result.failed("操作失败，用户权限不足");
            //检查工作流是否为上线状态
            if (processDefinition.getReleaseState() == ReleaseState.ONLINE) return Result.failed("上线状态，不可操作");
            processDefinitionLog.setId(processDefinition.getId());
            baseMapper.updateById(processDefinitionLog);
            //当作业流存在dependent作业时，保存更新作业流血缘关系
            //删除旧血缘关系
            processLineageMapper.delete(new QueryWrapper<ProcessLineage>().eq("dest_process_code",processDefinitionLog.getCode()));
            List<TaskNodeParam> taskNodeParams = processDefinitionLog.getTaskNodeParams();
            List<ProcessLineage> processLineages=new ArrayList<>();
            for (TaskNodeParam taskNodeParam : taskNodeParams) {
                if(taskNodeParam.getTaskType()== TaskType.DEPENDENT){
                    DependentParameters dependentParameters = taskNodeParam.getDependentParameters();
                    List<DependentTaskModel> dependTaskList = dependentParameters.getDependTaskList();
                    for (DependentTaskModel dependentTaskModel : dependTaskList) {
                        for (DependentItem dependentItem : dependentTaskModel.getDependItemList()) {
                            processLineages.add(new ProcessLineage(dependentItem.getDefinitionCode(),processDefinition.getCode()));
                        }
                    }
                }
            }
            if(!processLineages.isEmpty()){
                processLineageMapper.batchInsert(processLineages);
            }
            return Result.succeed("操作成功");
        } else return Result.failed("作业流不存在");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result delVersion(SysUser user, Long logId) {
        ProcessDefinitionLog processDefinitionLog = processDefinitionLogMapper.selectById(logId);
        ProcessDefinition processDefinition = baseMapper.queryByCode(processDefinitionLog.getCode(), user.getCurrentProjectId());
        if (processDefinition != null) {
            //检查用户是否由权限
            if (!checkOperationPermission(user, processDefinition)) return Result.failed("操作失败，用户权限不足");
            //作业流当前版本不可删除
            if (processDefinition.getVersion() == processDefinitionLog.getVersion())
                return Result.failed("作业流当前版本不可删除");
            processDefinitionLogMapper.deleteById(logId);
            //删除版本对应的process_task_relation
            processTaskRelationLogMapper.delete(new QueryWrapper<ProcessTaskRelationLog>()
                    .eq("process_definition_code", processDefinitionLog.getCode())
                    .eq("process_definition_version", processDefinitionLog.getVersion()));
            //删除版本对应的process instance
            processInstanceMapper.delete(new QueryWrapper<ProcessInstance>()
                    .eq("process_definition_code", processDefinitionLog.getCode())
                    .eq("process_definition_version", processDefinitionLog.getVersion()));
            return Result.succeed("操作成功");
        } else return Result.failed("作业流不存在");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result delProcess(SysUser user, Long processId) {
        ProcessDefinition processDefinition = baseMapper.selectById(processId);
        if (processDefinition != null) {
            //检查用户是否有权限
            if (!checkOperationPermission(user, processDefinition)) return Result.failed("操作失败，用户权限不足");
            //检查工作流是否为上线状态
            if (processDefinition.getReleaseState() == ReleaseState.ONLINE) return Result.failed("上线状态，不可操作");
            baseMapper.deleteById(processId);
            //删除所有版本
            processDefinitionLogMapper.delete(new QueryWrapper<ProcessDefinitionLog>().eq("code", processDefinition.getCode()));
            //删除所有process_task_relation
            processTaskRelationMapper.delete(new QueryWrapper<ProcessTaskRelation>().eq("process_definition_code", processDefinition.getCode()));
            //删除process instance
            processInstanceMapper.delete(new QueryWrapper<ProcessInstance>()
                    .eq("process_definition_code", processDefinition.getCode()));
            return Result.succeed("操作成功");
        } else return Result.failed("作业流不存在");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result release(SysUser user, Long processId) {
        ProcessDefinition processDefinition = baseMapper.selectById(processId);
        if (processDefinition != null) {
            processDefinition.setReleaseState(processDefinition.getReleaseState() == ReleaseState.ONLINE ? ReleaseState.OFFLINE : ReleaseState.ONLINE);
            //如果是下线操作，该流程的定时器同时下线
            if (processDefinition.getReleaseState() == ReleaseState.OFFLINE) {
                //判断流程是否被已上线的定时器流程作为子流程引用
                List<ScheduleSubProcess> scheduleSubProcess = scheduleSubProcessMapper.selectList(new QueryWrapper<ScheduleSubProcess>().eq("subprocess_code", processDefinition.getCode()));
                if (!scheduleSubProcess.isEmpty()) {
                    List<Long> codes = scheduleSubProcess.stream().map(x -> x.getScheduleProcessCode()).collect(Collectors.toList());
                    return Result.failed("该流程被流程：" + codes + " 作为子流程引用，并且定时器已上线，请先将定时器下线在操作");
                }
                Schedule schedule = scheduleMapper.queryByProcessDefinitionCode(processDefinition.getCode());
                if (schedule != null) {
                    log.info("set schedule offline, project id: {}, schedule id: {}, process definition code: {}", processDefinition.getProId(), schedule.getId(), processDefinition.getCode());
                    schedule.setReleaseState(ReleaseState.OFFLINE);
                    int updateSchedule = scheduleMapper.updateById(schedule);
                    if (updateSchedule == 0) {
                        throw new ServiceException(Status.OFFLINE_SCHEDULE_ERROR.getMsg());
                    }
                    scheduleSubProcessMapper.delete(new QueryWrapper<ScheduleSubProcess>().eq("schedule_id", schedule.getId()));
                    scheduleService.deleteSchedule(processDefinition.getProId(), schedule.getId());
                }
            }
            updateById(processDefinition);
            return Result.succeed("操作成功");
        } else return Result.failed("作业流不存在");
    }

    @Override
    public ProcessDefinitionLog findProcessLogDtl(Long proId, Long code, Integer version) {
        ProcessDefinitionLog processDefinitionLog = processDefinitionLogMapper.findProcessLogDtl(proId, code, version);
        if (processDefinitionLog != null) {
            List processTaskRelations = processTaskRelationLogMapper.selectList(new QueryWrapper<ProcessTaskRelationLog>().eq("pro_id", proId).eq("process_definition_code", code).eq("process_definition_version", version));
            processDefinitionLog.setTaskRelationList(processTaskRelations);
        }
        return processDefinitionLog;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result copyProcess(SysUser user, Long processId) throws SnowFlakeUtils.SnowFlakeException {
        ProcessDefinition processDefinition = getById(processId);
        if (!processDefinition.getProId().equals(user.getCurrentProjectId())) {
            return Result.failed("操作失败,非当前项目作业流不可复制");
        }
        processDefinition.setId(null);

        long code = SnowFlakeUtils.getInstance().nextId();
        List<ProcessTaskRelationLog> processTaskRelations = processTaskRelationLogMapper.selectList(new QueryWrapper<ProcessTaskRelationLog>().eq("process_definition_code", processDefinition.getCode()).eq("process_definition_version", processDefinition.getVersion()));
        for (ProcessTaskRelation processTaskRelation : processTaskRelations) {
            processTaskRelation.setId(null);
            processTaskRelation.setProcessDefinitionCode(code);
            processTaskRelation.setProcessDefinitionVersion(1);
        }
        processDefinition.setTaskRelationList(processTaskRelations);
        processDefinition.setCode(code);
        processDefinition.setReleaseState(ReleaseState.OFFLINE);
        processDefinition.setScheduleReleaseState(ReleaseState.OFFLINE);
        processService.saveProcessDefine(processDefinition, true);
        processService.saveTaskRelation(user.getCurrentProjectId(), processDefinition.getCode(), processDefinition.getVersion(), processDefinition.getTaskRelationList());
        ProcessDefinitionOwners owners = new ProcessDefinitionOwners();
        owners.setProcessDefinitionId(processDefinition.getId());
        owners.setOwners(Arrays.asList(user.getUsername()));
        processDefinitionOwnersMapper.insert(owners);
        //当作业流存在dependent作业时，保存更新作业流血缘关系
        //删除旧血缘关系
        List<TaskNodeParam> taskNodeParams = processDefinition.getTaskNodeParams();
        List<ProcessLineage> processLineages=new ArrayList<>();
        for (TaskNodeParam taskNodeParam : taskNodeParams) {
            if(taskNodeParam.getTaskType()== TaskType.DEPENDENT){
                DependentParameters dependentParameters = taskNodeParam.getDependentParameters();
                List<DependentTaskModel> dependTaskList = dependentParameters.getDependTaskList();
                for (DependentTaskModel dependentTaskModel : dependTaskList) {
                    for (DependentItem dependentItem : dependentTaskModel.getDependItemList()) {
                        processLineages.add(new ProcessLineage(dependentItem.getDefinitionCode(),processDefinition.getCode()));
                    }
                }
            }
        }
        if(!processLineages.isEmpty()){
            processLineageMapper.batchInsert(processLineages);
        }
        return Result.succeed("操作成功");
    }

    /**
     * Encapsulates the TreeView structure
     *
     * @param code  process definition code
     * @param limit limit
     * @return tree view json data
     */
    @Override
    public TreeViewEntity viewTree(long code, Integer limit) {
        Map<String, Object> result = new HashMap<>();
        ProcessDefinition processDefinition = baseMapper.queryByCode(code, 0l);
        if (null == processDefinition) {
            return null;
        }
        List<ProcessTaskRelation> processTaskRelations = processTaskRelationMapper.selectList(new QueryWrapper<ProcessTaskRelation>()
                .eq("process_definition_code", processDefinition.getCode()));
        Map<String, Set<String>> dag = new HashMap<>();
        for (ProcessTaskRelation processTaskRelation : processTaskRelations) {
            if (processTaskRelation.getPreTaskName() == null) {
                String key = "DAG";
                Set value = dag.getOrDefault(key, new HashSet<>());
                value.add(processTaskRelation.getPostTaskName());
                dag.put(key, value);
            } else {
                String key = processTaskRelation.getPreTaskName();
                Set value = dag.getOrDefault(key, new HashSet<>());
                value.add(processTaskRelation.getPostTaskName());
                dag.put(key, value);
            }
        }
        List<ProcessInstance> processInstanceList = processInstanceMapper.queryByProcessDefineCodeVersion(processDefinition.getCode(), processDefinition.getVersion(), limit);
        processInstanceList.forEach(processInstance -> processInstance.setDuration(DateUtils.format2Duration(processInstance.getStartTime(), processInstance.getEndTime())));
        Map<String, Map<Long,TaskInstance>> taskInstanceMaps = new HashMap<>();
        if (!processInstanceList.isEmpty()) {
            List<Long> ids = processInstanceList.stream().map(x -> x.getId()).collect(Collectors.toList());
            List<TaskInstance> taskInstances = taskInstanceMapper.findByProcessInsIds(ids);
            for (TaskInstance taskInstance : taskInstances) {
                taskInstance.setDuration(DateUtils.format2Duration(taskInstance.getStartTime(), taskInstance.getEndTime()));
                Map<Long,TaskInstance> taskInstanceMap = taskInstanceMaps.getOrDefault(taskInstance.getName(), new HashMap<>());
                taskInstanceMap.put(taskInstance.getProcessInstanceId(),taskInstance);
                taskInstanceMaps.put(taskInstance.getName(), taskInstanceMap);
            }
        }

        TreeViewEntity parentTreeViewDto = new TreeViewEntity();
        parentTreeViewDto.setName("DAG");
        // Specify the process definition, because it is a TreeView for a process definition
        for (ProcessInstance processInstance : processInstanceList) {
            Date endTime = processInstance.getEndTime() == null ? new Date() : processInstance.getEndTime();
            parentTreeViewDto.getInstances().add(new Instance(processInstance.getId(), processInstance.getName(), processInstance.getProcessDefinitionCode(),
                    null, processInstance.getState(), processInstance.getStartTime(), endTime, processInstance.getHost(),
                    DateUtils.format2Readable(endTime.getTime() - processInstance.getStartTime().getTime()), processInstance.getId()));

        }

        parentTreeViewDto.setChildren(getChildren(parentTreeViewDto, dag, taskInstanceMaps));
        return parentTreeViewDto;
    }

    private List<TreeViewEntity> getChildren(TreeViewEntity parent, Map<String, Set<String>> dag, Map<String, Map<Long,TaskInstance>> taskInstanceMaps) {
        Set<String> childrens = dag.get(parent.getName());
        List<TreeViewEntity> treeViewEntities = new ArrayList<>();
        if(childrens==null) return treeViewEntities;
        for (String children : childrens) {
            TreeViewEntity childrenTreeViewDto = new TreeViewEntity();
            childrenTreeViewDto.setName(children);
            Map<Long,TaskInstance> taskInstanceMap = taskInstanceMaps.get(children);
            List<Instance> instances = parent.getInstances();
            for (Instance instance : instances) {
                TaskInstance taskInstance =taskInstanceMap!=null?taskInstanceMap.get(instance.getProcessInstanceId()):null;
                if(taskInstance!=null){
                    Date endTime = taskInstance.getEndTime() == null ? new Date() : taskInstance.getEndTime();
                    Long subProcessCode = 0l;
                    // if process is sub process, the return sub id, or sub id=0
                    if (taskInstance.isSubProcess()) {
                        SubProcessParameters subProcessParameters = JSONUtils.parseObject(taskInstance.getTaskContent(), SubProcessParameters.class);
                        subProcessCode = subProcessParameters.getProcessDefinitionCode();
                    }
                    childrenTreeViewDto.getInstances().add(new Instance(taskInstance.getId(), taskInstance.getName(), taskInstance.getTaskDefinitionId(),
                            taskInstance.getTaskType(), taskInstance.getState(), taskInstance.getStartTime(), endTime, taskInstance.getHost(),
                            DateUtils.format2Readable(endTime.getTime() - taskInstance.getStartTime().getTime()), subProcessCode, taskInstance.getProcessInstanceId()));
                } else {
                    childrenTreeViewDto.getInstances().add(new Instance(-1l, "not running", 0l, null,instance.getProcessInstanceId()));
                }
            }
            childrenTreeViewDto.setChildren(getChildren(childrenTreeViewDto, dag, taskInstanceMaps));
            treeViewEntities.add(childrenTreeViewDto);
        }
        return treeViewEntities;
    }

    /**
     * 只有项目管理员和作业流负责人拥有修改权限
     *
     * @param user
     * @param processDefinition
     * @return
     */
    private boolean checkOperationPermission(SysUser user, ProcessDefinition processDefinition) {
        if (user.getCurrentProjectId().equals(processDefinition.getProId()) && UserRoleUtil.checkProAdmin(user.getProRoles()))
            return true;
        ProcessDefinitionOwners owners = processDefinitionOwnersMapper.selectOne(new QueryWrapper<ProcessDefinitionOwners>().eq("process_definition_id", processDefinition.getId()));
        if (owners != null && owners.getOwners().contains(user.getUsername())) return true;
        return false;
    }
}
